/**
 * 文件名   :   MyBean.java
 * 版权       :   <版权/公司名>
 * 描述       :   <描述>
 * @author  chen
 * 版本       :   <版本>
 * 修改时间：      2016年10月23日
 * 修改内容：      <修改内容>
 */
package com.one.mycommons;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.apache.log4j.Logger;

/**
 * <一句话功能简述>
 * <功能详细描述>
 * @author    chen
 * @version   [版本号，2016年10月23日]
 * @see       [相关类/方法]
 * @since     [产品/模块版本]
 */

public class CopyBean {
	
	public static Logger log = Logger.getLogger(CopyBean.class);

	/**
	 * <一句话功能简述> 实体间 复制数据 src --> dst （一次性少量复制）
	 * <功能详细描述>
	 * @see [类、类#方法、类#成员]
	 */
	public static void copyField(Object src, Object dst,String... filter) {
		List<String> filters = Arrays.asList(filter);
		List<Field> fields = new ArrayList<Field>();
		Class<?> classobj = src.getClass();
		if (null != classobj) {
			Field[] fs = classobj.getDeclaredFields();
			for (Field field : fs) {
				field.setAccessible(true);
				fields.add(field);
			}
			fields = findFatherField(classobj, fields);
		}
		for (Field field : fields) {
			if (filters.contains(field.getName())) {
				continue;
			}
			// dst  obj's property set value
			try {
				field.set(dst, field.get(src));
			} catch (SecurityException e) {
				log.error(field.getName() + " is unsafe : SecurityException");
			} catch (IllegalArgumentException e) {
				log.error(field.getName() + " is inexist or null or OutOfRange : ArgumentException ");
			} catch (IllegalAccessException e) {
				log.error(field.getName() + " Access is false : AccessException");
			}
		}
	}
	
	/**
	 * <一句话功能简述> 实体间 复制数据 src --> dst（当一次性拷贝循环超30000时，效率稍高点 ，否则copyField效率高 ）
	 * <功能详细描述>
	 * @throws IntrospectionException 
	 * @see [类、类#方法、类#成员]
	 */
	public static void copyWithIntrospector(Object src, Object dst,String... filter) throws IntrospectionException {
		List<String> filters = Arrays.asList(filter);
		BeanInfo dstBeanInfo = Introspector.getBeanInfo(dst.getClass()); // 获取类属性
//        Object obj = type.newInstance(); // 创建 JavaBean 对象
		BeanInfo srcBeanInfo = Introspector.getBeanInfo(src.getClass()); // 获取类属性
	    PropertyDescriptor[] srcPropertyDescriptors =  srcBeanInfo.getPropertyDescriptors();
	    for (PropertyDescriptor property : srcPropertyDescriptors) {
	    	String pName = property.getName();
	    	if (filters.contains(pName)) {
				continue;
			}
	    	if (!"class".equals(pName)) {
	    		Method readMethod = property.getReadMethod();
	    		 try {
					Object result = readMethod.invoke(src, new Object[0]);
					if (null == result) {
						continue;
					}
					property.getWriteMethod().invoke(dst, result);
				} catch (IllegalAccessException e) {
					log.error(pName + " Access is false : AccessException");
				} catch (IllegalArgumentException e) {
					log.error(pName + " is inexist or null or OutOfRange : ArgumentException ");
				} catch (InvocationTargetException e) {
					log.error(pName + " is Invocation Exception");
				}
	    	}
		}
	}
	
	/**
	 * <一句话功能简述>
	 * <功能详细描述>
	 * @see [类、类#方法、类#成员]
	 */
	private static List<Field> findFatherField(Class<?> classObj, List<Field> fields) {
		Class<?> classz = classObj.getSuperclass();
		if (null != classz) {
			Field[] field_array = classz.getDeclaredFields();
			if (field_array.length > 0) {
				for (Field field : field_array) {
					field.setAccessible(true);
					fields.add(field);
				}
				findFatherField(classz,fields);
			}
		}
		return fields;
	}
}
